﻿using System;
using System.Linq;
using System.Xml.Linq;
using SoftwareLogistics.SharepointClient.Models;
using SoftwareLogistics.SharepointClient.Library.ListsService;
using System.Collections.Generic;
using System.Diagnostics;
using SoftwareLogistics.SharepointClient.Library;
using SoftwareLogistics.SharepointClient.Library.Models;

namespace SoftwareLogistics.SharepointClient.Services
{
    

    public class SPListService
    {
        public event EventHandler<GotFieldsEventArgs> GotMetaData;
        public event EventHandler<GotListRowsEventArgs> GotListRows;
        public event EventHandler RecordUpdated;
        public event EventHandler FailedUpdatingRecord;

        private string _siteName;
        private string _listName;

        ListsSoapClient _listService;
        protected ListsSoapClient ListService
        {
            get
            {
                if (_listService == null)
                {


                    _listService = new ListsSoapClient();
                    _listService.CookieContainer = Common.AuthService.GetCookieJar;


                    _listService.Endpoint.Address = new System.ServiceModel.EndpointAddress(new Uri("http://slsys.homeip.net:8000/pm/_vti_bin/lists.asmx"));


                    _listService.GetListAndViewCompleted += (sndr, args) =>
                    {
                        var list = new SPList { Name = _listName, SiteName = _siteName };
                        var listFields = args.Result.Descendants(XName.Get("List", Common.SP_NS)).First();
                        var viewFields = args.Result.Descendants(XName.Get("View", Common.SP_NS)).First();
                        list.ListId = new Guid(listFields.Attribute("Name").Value);
                        list.ViewId = new Guid(viewFields.Attribute("Name").Value);

                        var lists = from element 
                                        in listFields.Descendants(XName.Get("Field", Common.SP_NS))
                                    select SPField.Create(element);

                        foreach (var field in lists)
                        {
                            var key = field.Name;
                            key = key.Replace("_x0020_", " ");

                            if (!list.Fields.ContainsKey(key))
                                list.Fields.Add(key, field);
                        }


                        if (GotMetaData != null)
                            GotMetaData(this, new GotFieldsEventArgs() { List = list });
                    };

                    _listService.UpdateListItemsCompleted += (sndr, args) =>
                    {
                        if (args.Error != null)
                        {
                            Debug.WriteLine("ERROR UPDATING RECORD: " + args.Error.Message);
                            FailedUpdatingRecord(this, null);
                        }
                        else
                        {
                            Debug.WriteLine(Convert.ToString(args.Result));

                            RecordUpdated(this, null);
                        }
                    };

                    _listService.GetListItemsCompleted += (sndr, args) =>
                    {
                        var eventArgs = new GotListRowsEventArgs { Rows = null, ListMetaData = args.UserState as SPList };
                        if (args.Error == null)
                        {
                            var rows = args.Result.Descendants(XName.Get("row", "#RowsetSchema"));
                            eventArgs.Rows = new List<SPDataRow>();

                            foreach (var row in rows)
                            {
                                SPDataRow dataRow = SPDataRow.Create(row);
                                dataRow.ListName = eventArgs.ListMetaData.Name;
                                eventArgs.Rows.Add(dataRow);
                            }
                        }

                        if (GotListRows != null)
                            GotListRows(this, eventArgs);
                    };

                    _listService.GetListCompleted += (sndr, args) =>
                    {
                        if (args.Error == null)
                        {
                            if (GotMetaData != null)
                                GotMetaData(this, null);

                            return;
                        }

                        var list = new SPList { Name = _listName, ListId = new Guid(args.Result.Attribute("ID").Value), SiteName = _siteName };
                        var rows = args.Result.Descendants(XName.Get("Field", Common.SP_NS));
                        
                        var lists = from element in rows
                                    select SPField.Create(element);

                        foreach (var field in lists)
                        {
                            var key = field.Name;
                            key = key.Replace("_x0020_", " ");

                            if (!list.Fields.ContainsKey(key))
                                list.Fields.Add(key, field);
                        }

                        if (GotMetaData != null)
                            GotMetaData(this, new GotFieldsEventArgs(){List = list});
                    };
                }

                return _listService;
            }
        }

        public void GetListRows(string listName)
        {
            ListService.GetListItemsAsync(listName, String.Empty, null, null, null, null, "6de8378a-146a-440d-898a-923931f69f53", Common.ListMetaData[listName]);
        }

        public void GetListRows(string listName, SPQuery query)
        {            
            ListService.GetListItemsAsync(listName, String.Empty, query.GetElement(), null, null, null, "6de8378a-146a-440d-898a-923931f69f53", Common.ListMetaData[listName]);
        }

        public void GetListMetaData(string siteName, string listName)
        {
            _siteName = siteName;
            _listName = listName;
            ListService.GetListAndViewAsync(listName, string.Empty);
            //ListService.GetListAsync(listName);   
        }


        private XElement GetFormXML(string method, Guid id)
        {
            var methodElement = new XElement("Method");
            methodElement.Add(new XAttribute("ID", "1"));
            methodElement.Add(new XAttribute("Cmd", method));

            //var doc = new XElement(
               //new XDeclaration("1.0", "utf-8", null),
            var doc = new XElement("Batch",
                new XAttribute("OnError", "Continue"),
                new XAttribute("ListVersion", "1?"),
                new XAttribute("ViewName", id),
                 methodElement);
            
            //);

            return doc;
        }

        private void AddFields(XElement methodElement, IEnumerable<SPField> fields)
        {
            foreach (var field in fields)
            {
                if (!String.IsNullOrEmpty(field.Value))
                {
                    var fieldElement = new XElement("Field");
                    fieldElement.Add(new XAttribute("Name", field.Name));
                    if (field.Value != null)
                        fieldElement.Value = field.Value;

                    methodElement.Add(fieldElement);
                }
            }
        }
        
        public void UpdateRecord(bool isEdit, string listName, IEnumerable<SPField> fields)
        {
            var list = Common.ListMetaData[listName];

            var root = GetFormXML(isEdit ? "Update" : "New", list.ViewId);
            var element = root.Descendants().Where(ele => ele.Name == "Method").FirstOrDefault();
            AddFields(element, fields);

            Debug.WriteLine(Convert.ToString(root));

            ListService.UpdateListItemsAsync(list.ListId.ToString(), root);
        }
    }
}
